package com.xyzwps.harbor.handler.user;

import com.xyzwps.harbor.handler.RequestAttrs;
import com.xyzwps.harbor.service.SessionService;
import com.xyzwps.harbor.service.UserService;
import com.xyzwps.harbor.service.VcodeService;
import com.xyzwps.harbor.util.Dict;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.util.Pair;
import org.springframework.http.ResponseCookie;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

import java.util.Map;

import static com.xyzwps.harbor.util.HarborException.*;

@Component
public class UserHandler {

    @Autowired
    private UserService userService;

    @Autowired
    private VcodeService vcodeService;

    @Autowired
    private SessionService sessionService;

    public Mono<ServerResponse> preRegister(ServerRequest req) {
        return vcodeService.generateVcodeScope()
                .flatMap(vcodeScope -> ServerResponse.ok().bodyValue(Map.of("scope", vcodeScope.getScope())));
    }

    public Mono<ServerResponse> register(ServerRequest req) {
        return req.bodyToMono(RegisterUserDto.class)
                .map(RegisterUserDto::validate)
                .flatMap(dto -> vcodeService.validateVcode(dto.getVcode(), dto.getScope()).then(Mono.just(dto)))
                .flatMap(dto -> userService.createUser(dto.getUsername(), dto.getPassword()))
                .flatMap(newUser -> ServerResponse.ok().bodyValue(newUser));
    }

    public Mono<ServerResponse> login(ServerRequest req) {
        return req.bodyToMono(LoginDto.class)
                .map(LoginDto::validate)
                .flatMap(dto -> userService.login(dto.getUsername(), dto.getPassword()))
                .flatMap(user -> sessionService.createSession(user).map(sid -> Pair.of(user, sid)))
                .flatMap(pair -> ServerResponse.ok()
                        .cookie(ResponseCookie.from(Dict.COOKIE_SID, pair.getSecond()).build())
                        .bodyValue(pair.getFirst())
                );
    }

    public Mono<ServerResponse> profile(ServerRequest req) {
        var user = RequestAttrs.getUser(req);
        return ServerResponse.ok().bodyValue(user);
    }

    public Mono<ServerResponse> getUser(ServerRequest req) {
        var userIdStr = req.pathVariable("userId" );
        var userId = Long.parseLong(userIdStr);
        return userService.getUserByUserId(userId)
                .switchIfEmpty(Mono.error(badRequestEx("找不到用户 " + userId)))
                .flatMap(user -> ServerResponse.ok().bodyValue(user));
    }

}
